package com.zhiche.lisa.bms.service.psup.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiche.lisa.bms.dao.mapper.psup.PsupOtherExpensisesMapper;
import com.zhiche.lisa.bms.dao.model.psup.PsupOtherExpensises;
import com.zhiche.lisa.bms.enums.SdCommonEnum;
import com.zhiche.lisa.bms.pojo.dto.util.LspFleetDTO;
import com.zhiche.lisa.bms.pojo.vo.psup.PsupOtherExpensisesVO;
import com.zhiche.lisa.bms.service.psup.PsupOtherExpensisesService;
import com.zhiche.lisa.bms.service.utils.LspUtil;
import com.zhiche.lisa.bms.utils.ToolCommonUtils;
import com.zhiche.lisa.core.supports.BaseException;
import com.zhiche.lisa.core.utils.Account.AccountUtil;
import com.zhiche.lisa.core.utils.Account.JwtAccountVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 人送其他费用 服务实现类
 * </p>
 *
 * @author linbao
 * @since 2019-06-18
 */
@Service
@Slf4j
public class PsupOtherExpensisesServiceImpl extends ServiceImpl<PsupOtherExpensisesMapper, PsupOtherExpensises> implements PsupOtherExpensisesService {

    @Autowired
    private LspUtil lspUtil;

    /**
     * 分页查询
     *
     * @param page
     * @return
     */
    @Override
    public Page<PsupOtherExpensisesVO> querySdOtherExpensisesPage(Page<PsupOtherExpensises> page) {
        EntityWrapper<PsupOtherExpensises> ew = this.buildCondition(page.getCondition());
        List<PsupOtherExpensises> otherExpensisesList = baseMapper.selectPage(page, ew);
        Page<PsupOtherExpensisesVO> voPage = new Page<>();
        BeanUtils.copyProperties(page, voPage);
        if (CollectionUtils.isNotEmpty(otherExpensisesList)) {
            List<PsupOtherExpensisesVO> voList = Lists.newArrayList();
            otherExpensisesList.forEach(psupOtherExpensises -> {
                PsupOtherExpensisesVO vo = new PsupOtherExpensisesVO();
                BeanUtils.copyProperties(psupOtherExpensises, vo);
                voList.add(vo);
            });
            voPage.setRecords(voList);
        }
        return voPage;
    }

    /**
     * 条件查询
     *
     * @param condition
     * @return
     */
    @Override
    public List<PsupOtherExpensisesVO> querySdOtherExpensisesByCondition(Map<String, Object> condition) {
        EntityWrapper<PsupOtherExpensises> ew = this.buildCondition(condition);
        List<PsupOtherExpensises> otherExpensisesList = baseMapper.selectList(ew);
        if (CollectionUtils.isNotEmpty(otherExpensisesList)) {
            List<PsupOtherExpensisesVO> voList = Lists.newArrayList();
            otherExpensisesList.forEach(psupOtherExpensises -> {
                PsupOtherExpensisesVO vo = new PsupOtherExpensisesVO();
                BeanUtils.copyProperties(psupOtherExpensises, vo);
                // 状态
                if (Objects.nonNull(psupOtherExpensises.getStatus())) {
                    vo.setStatusStr(SdCommonEnum.getStatusValue(psupOtherExpensises.getStatus()));
                }
                // 生效时间
                if (Objects.nonNull(psupOtherExpensises.getEffectiveDate())) {
                    vo.setEffectiveDateStr(new DateTime(psupOtherExpensises.getEffectiveDate()).toString(ToolCommonUtils.yyyyMMdd));
                }
                // 失效时间
                if (Objects.nonNull(psupOtherExpensises.getInvalidDate())) {
                    vo.setInvalidDateStr(new DateTime(psupOtherExpensises.getInvalidDate()).toString(ToolCommonUtils.yyyyMMdd));
                }
                voList.add(vo);
            });
            return voList;
        }
        return null;
    }

    /**
     * 批量审核
     *
     * @param idList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<String> auditBatchOtherExpensisesByIdList(List<Long> idList) {
        this.verifyForCreateAndAudit(idList, "存在非新增的数据, 不可审核");
        List<PsupOtherExpensises> psupOtherExpensisesList = this.selectBatchIds(idList);

        List<PsupOtherExpensises> updateOtherExpensizeList = Lists.newArrayList();
        JwtAccountVO account = AccountUtil.getAccountInfoFromSecurityContext();
        if (CollectionUtils.isNotEmpty(psupOtherExpensisesList)) {
            List<String> resultMsgList = Lists.newArrayList();
            psupOtherExpensisesList.forEach(otherExpensises -> {
                Integer countByFleet = verifyOtherExpensises(otherExpensises);
                if (countByFleet > 0) {
                    StringBuilder sb = new StringBuilder();
                    sb.append("数据:").append("车队-").append(otherExpensises.getFleetName()).append(":线路有效期冲突");
                    resultMsgList.add(sb.toString());
                } else {
                    // 2019-10-30 创建人
                    otherExpensises.setActivitiName(account.getUsername());
                    otherExpensises.setStatus(SdCommonEnum.AUDIT.getCode());
                    updateOtherExpensizeList.add(otherExpensises);
                }
            });
            if (CollectionUtils.isNotEmpty(resultMsgList)) {
                return resultMsgList;
            }

            if (CollectionUtils.isNotEmpty(updateOtherExpensizeList)) {
                this.updateBatchById(updateOtherExpensizeList);
            }
        }
        return null;
    }

    /**
     * 批量删除
     *
     * @param idList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<String> deleteBatchOtherExpensisesByIdList(List<Long> idList) {
        this.verifyForCreateAndAudit(idList, "存在非新增的数据, 不可删除");
        this.deleteBatchIds(idList);
        return null;
    }

    /**
     * 针对excel的批量新增
     *
     * @param voList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<String> createBatchOtherExpensises(List<PsupOtherExpensisesVO> voList, String token) {
        List<String> resultMsgList = this.verifyInsertParam(voList, token);
        if (CollectionUtils.isNotEmpty(resultMsgList)) {
            return resultMsgList;
        }
        List<PsupOtherExpensises> insertList = Lists.newArrayList();
        JwtAccountVO account = AccountUtil.getAccountInfoFromSecurityContext();
        voList.forEach(otherExpensiseVo -> {
            PsupOtherExpensises insertObj = new PsupOtherExpensises();
            BeanUtils.copyProperties(otherExpensiseVo, insertObj);
            insertObj.setGmtCreate(new Date());
            // 2019-10-30 创建人/上传人
            insertObj.setCreatorName(account.getUsername());
            insertList.add(insertObj);
        });
        if (CollectionUtils.isNotEmpty(insertList)) {
            this.insertBatch(insertList);
        }
        return null;
    }

    private Integer verifyOtherExpensises(PsupOtherExpensises psupOtherExpensises) {
        Map<String, Object> condition = Maps.newHashMap();
        if (Objects.nonNull(psupOtherExpensises.getEffectiveDate())) {
            condition.put("effectiveDate", new DateTime(psupOtherExpensises.getEffectiveDate()).toString(ToolCommonUtils.yyyyMMdd));
        }
        if (Objects.nonNull(psupOtherExpensises.getInvalidDate())) {
            condition.put("invalidDate", new DateTime(psupOtherExpensises.getInvalidDate()).toString(ToolCommonUtils.yyyyMMdd));
        }
        condition.put("fleetId", psupOtherExpensises.getFleetId());
        condition.put("priceType", psupOtherExpensises.getPriceType());
        condition.put("contractVehicle", psupOtherExpensises.getContractVehicle());
        condition.put("notEqId", psupOtherExpensises.getId());
        condition.put("status", SdCommonEnum.AUDIT.getCode());

        // 起运/目的 省市区
        condition.put("startProvince", psupOtherExpensises.getStartProvince());
        condition.put("startCity", psupOtherExpensises.getStartCity());
        condition.put("startCounty", psupOtherExpensises.getStartCounty());
        condition.put("startName", psupOtherExpensises.getStartName());
        condition.put("endProvince", psupOtherExpensises.getEndProvince());
        condition.put("endCity", psupOtherExpensises.getEndCity());
        condition.put("endCounty", psupOtherExpensises.getEndCounty());
        condition.put("endName", psupOtherExpensises.getEndName());
        return baseMapper.verifyIsExistDate(condition);
    }

    /**
     * 查询条件
     *
     * @param condition
     * @return
     */
    private EntityWrapper<PsupOtherExpensises> buildCondition(Map<String, Object> condition) {
        EntityWrapper<PsupOtherExpensises> ew = new EntityWrapper<>();
        ew.orderBy("id desc");
        if (Objects.nonNull(condition)) {

            Object effectiveDateObj = condition.get("effectiveDate");
            if (Objects.nonNull(effectiveDateObj) && StringUtils.isNotBlank(effectiveDateObj.toString())) {
                Date effectiveDate = ToolCommonUtils.getDateByStr(effectiveDateObj.toString(), ToolCommonUtils.yyyyMMdd);
                ew.le("effective_date", effectiveDate);
                ew.ge("invalid_date", effectiveDate);
            }
            // 车队
            startAndEndInfo(condition, ew, "fleetId", "fleet_id", false);
            // 车队
            startAndEndInfo(condition, ew, "fleetName", "fleet_name", true);
            // 状态
            startAndEndInfo(condition, ew, "status", "status", false);
            // 费用类型名称
            startAndEndInfo(condition, ew, "priceType", "price_type", true);
            // 合同车型名称
            startAndEndInfo(condition, ew, "contractVehicle", "contract_vehicle", true);
            // 起运省
            startAndEndInfo(condition, ew, "startProvince", "start_province", true);
            // 起运市
            startAndEndInfo(condition, ew, "startCity", "start_city", true);
            // 起运区
            startAndEndInfo(condition, ew, "startCounty", "start_county", true);
            // 起运名称
            startAndEndInfo(condition, ew, "startName", "start_name", true);
            // 目的省
            startAndEndInfo(condition, ew, "endProvince", "end_province", true);
            // 目的市
            startAndEndInfo(condition, ew, "endCity", "end_city", true);
            // 目的区
            startAndEndInfo(condition, ew, "endCounty", "end_county", true);
            // 目的名称
            startAndEndInfo(condition, ew, "endName", "end_name", true);
        }
        return ew;
    }

    private void startAndEndInfo(Map<String, Object> condition, EntityWrapper ew, String key, String column, boolean isLike) {
        // 车队名称
        Object value = condition.get(key);
        if (Objects.nonNull(value) && StringUtils.isNotBlank(value.toString())) {
            if (isLike) {
                ew.like(column, value.toString());
            } else {
                ew.eq(column, value.toString());
            }

        }
    }

    private void verifyForCreateAndAudit(List<Long> idList, String errorMsg) {
        if (CollectionUtils.isEmpty(idList)) {
            throw new BaseException("请选择数据");
        }
        EntityWrapper<PsupOtherExpensises> ew = new EntityWrapper<>();
        ew.in("id", idList);
        ew.ne("status", SdCommonEnum.NEW.getCode());
        int count = this.selectCount(ew);
        if (count > 0) {
            throw new BaseException(errorMsg);
        }
    }


    /**
     * 校验数据并获取车队id
     *
     * @param voList
     * @param token
     * @return
     */
    private List<String> verifyInsertParam(List<PsupOtherExpensisesVO> voList, String token) {
        Map<String, Long> fleetMap = getFleetMap(voList, token);
        if (Objects.nonNull(fleetMap)) {
            voList.stream()
                    .filter(fixedPriceVO -> StringUtils.isNotBlank(fixedPriceVO.getFleetName()))
                    .forEach(fixedPriceVO -> {
                        Long fleetId = fleetMap.get(fixedPriceVO.getFleetName());
                        if (Objects.nonNull(fleetId)) {
                            fixedPriceVO.setFleetId(fleetId);
                        }
                    });
        }
        List<String> resultMsgList = Lists.newArrayList();
        for (int i = 0, n = voList.size(); i < n; i++) {
            PsupOtherExpensisesVO psupOtherExpensisesVO = voList.get(i);
            StringBuilder sb = new StringBuilder();
            if (StringUtils.isBlank(sb) && Objects.isNull(psupOtherExpensisesVO.getEffectiveDate())) {
                sb.append("生效日期为空!");
            }
            if (StringUtils.isBlank(sb) && Objects.isNull(psupOtherExpensisesVO.getInvalidDate())) {
                sb.append("失效日期为空!");
            }
            if (StringUtils.isBlank(sb) && StringUtils.isBlank(psupOtherExpensisesVO.getPriceType())) {
                sb.append("价格类型为空!");
            }
            if (StringUtils.isBlank(sb) && StringUtils.isBlank(psupOtherExpensisesVO.getFleetName())) {
                sb.append("车队名称为空!");
            }
            if (StringUtils.isBlank(sb) && Objects.isNull(psupOtherExpensisesVO.getGrossAmount())) {
                sb.append("总金额为空!");
            }
            if (StringUtils.isNotBlank(sb)) {
                sb.insert(0, "行数:第" + (i + 1) + "行:");
                resultMsgList.add(sb.toString());
            }
        }
        return resultMsgList;
    }

    /**
     * 查询车队信息
     *
     * @param otherExpensisesVOList
     * @param token
     * @return
     */
    private Map<String, Long> getFleetMap(List<PsupOtherExpensisesVO> otherExpensisesVOList, String token) {
        List<LspFleetDTO> dtoList = Lists.newArrayList();
        otherExpensisesVOList.stream()
                .filter(otherExpensises -> StringUtils.isNotBlank(otherExpensises.getFleetName()))
                .forEach(otherExpensises -> {
                    LspFleetDTO lspFleetDTO = new LspFleetDTO();
                    lspFleetDTO.setFleetName(otherExpensises.getFleetName());
                    dtoList.add(lspFleetDTO);
                });
        List<LspFleetDTO> fleetList = lspUtil.getFleetAll(dtoList, token);
        if (CollectionUtils.isNotEmpty(fleetList)) {
            Map<String, Long> fleetMap = Maps.newHashMap();
            fleetList.forEach(fleet -> {
                fleetMap.put(fleet.getFleetName(), fleet.getId());
            });
            return fleetMap;
        }
        return null;
    }
}
